package com.code.point.service.impl;

import com.code.common.service.impl.BaseMySqlCrudServiceImpl;
import com.code.point.api.PointService;
import com.code.point.dao.PointMapper;
import com.code.point.model.po.Point;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 积分服务接口实现（积分基础服务层）
 *
 * @author tangyifei
 */
@Slf4j
@Service(
        version = "${service.version}",
        application = "${dubbo.application.id}",
        protocol = "${dubbo.protocol.id}",
        registry = "${dubbo.registry.id}",
        interfaceClass = PointService.class,
        cluster = "${dubbo.provider.cluster}",
        loadbalance = "${dubbo.provider.loadbalance}"
)
//@RefreshScope 配置文件数据实时刷新，也就是 nacos 管理平台修改了配置会实时同步获取（可根据实际情况配置是否添加）
@RefreshScope
public class PointServiceImpl extends BaseMySqlCrudServiceImpl<Point, Long> implements PointService {

    private static Map<String, Integer> maps = new HashMap<>();

    static {
        maps.put("one", 1);
        maps.put("two", 2);
        maps.put("three", 3);
    }

    private static List<String> list1 = new ArrayList<>();

    static {
        list1.add("tang");
        list1.add("yi");
        list1.add("fei");
    }

    @Resource
    private PointMapper pointMapper;

    /**
     * 支持不配置 key 程序也能正常运行的话，给它们加上默认值即可，仅仅多了一个 : 号，冒号后的值表示当 key 不存在时候使用的默认值，使用默认值时数组的 length = 0
     * <p>
     * 注意：@Value 注解不能和 @AllArgsConstructor 注解同时使用，否则会报错Consider defining a bean of type 'java.lang.String' in your configuration
     */
    @Value("${test.array1:}")
    private String[] testArray1;

    @Value("${test.array2:}")
    private int[] testArray2;

    @Value("${test.array3:}")
    private double[] testArray3;

    @Value("#{'${test.list:}'.empty ? null : '${test.list:}'.split(',')}")
    private List<String> testList;

    @Value("#{'${test.set:}'.empty ? null : '${test.set:}'.split(',')}")
    private Set<Integer> testSet;

    @Value("#{T(com.code.point.decoder.MapDecoder).decodeMap('${test.map1:}')}")
    private Map<String, String> map1;

    @Value("#{T(com.code.point.decoder.MapDecoder).decodeMap('${test.map2:}')}")
    private Map<String, String> map2;

    @Value("${point}")
    private String point;

    /**
     * 获取积分，用于测试使用nacos当分布式配置中心的动态刷新配置
     *
     * @return 积分
     */
    @Override
    public String getPoint() {
        log.info("当前积分：{}", point);
        return point;
    }

    @Override
    public String[] getArray() {
        return testArray1;
    }

    @Override
    public List<String> getList() {
        return testList;
    }

    @Override
    public Set<Integer> getSet() {
        return testSet;
    }

    @Override
    public Map<String, String> getMap() {
        return map1;
    }

    public static void main(String[] args) {
        // ++++++++++++++++代码规范1++++++++++++++++++
        // 若需频繁调用Collection.contains 方法则使用Set，
        // 在Java 集合类库中，List的contains 方法普遍时间复杂度为O(n)，
        // 若代码中需要频繁调用contains 方法查找数据则先将集合list 转换成HashSet 实现，将O(n) 的时间复杂度将为O(1)。
        List<Object> list = new ArrayList<>();
        list.add(1);
        list.add(1);
        list.add(2);
        list.add(3);
        Set<Object> set = new HashSet<>(list);
        for (int i = 0; i <= 10; i++) {
            //时间复杂度为O(1)
            if (set.contains(i)) {
                System.out.println("list contains " + i);
            }
        }

        System.out.println("+++++++++++++++++++++++++\r\n");

        // ++++++++++++++++代码规范2++++++++++++++++++
        // 对于集合类型的静态成员变量，应该使用静态代码块赋值，而不是使用集合实现来赋值。
        // 赋值静态成员变量正例
        list1.forEach(System.out::println);
        maps.forEach((key, value) -> {
            System.out.println(key + ":" + value);
        });

        System.out.println("+++++++++++++++++++++++++\r\n");

        // ++++++++++++++++代码规范3++++++++++++++++++
        // 避免使用BigDecimal(double)，BigDecimal(double) 存在精度损失风险，
        // 在精确计算或值比较的场景中可能会导致业务逻辑异常。
        System.out.println(BigDecimal.valueOf(0.11D));

        System.out.println("+++++++++++++++++++++++++\r\n");

        // ++++++++++++++++代码规范4++++++++++++++++++
        // 返回空数组和集合而非 null
        // 若程序运行返回null，需要调用方强制检测null，否则就会抛出空指针异常；
        // 返回空数组或空集合，有效地避免了调用方因为未检测null 而抛出空指针异常的情况，
        // 还可以删除调用方检测null 的语句使代码更简洁。
        //返回空数组和空集正例
//        public static Result[] getResults() {
//            return new Result[0];
//        }

        System.out.println(Collections.emptyList());

        System.out.println(Collections.emptyMap());

        System.out.println("+++++++++++++++++++++++++\r\n");

        // ++++++++++++++++代码规范5++++++++++++++++++
        //使用字符串String的split 方法时，传入的分隔字符串是正则表达式，则部分关键字（比如 .| 等）需要转义。
        // String.split(String regex) 正例
        String[] split2 = "a.ab.abc".split("\\.");
        // 结果为["a", "ab", "abc"]
        System.out.println(Arrays.toString(split2));
        String[] split3 = "a|ab|abc".split("\\|");
        // 结果为["a", "ab", "abc"]
        System.out.println(Arrays.toString(split3));


    }

}
